package com.mindata.blockchain.common;

import cn.hutool.core.collection.CollUtil;
import com.google.common.collect.Lists;
import com.mindata.blockchain.block.Block;
import com.mindata.blockchain.block.BlockHeader;
import com.mindata.blockchain.block.Instruction;
import com.mindata.blockchain.block.InstructionInfo;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * User: jasperxgwang
 * Date: 2018-7-26 11:36
 */
public class BlockUtils {

    /**
     * 区块 hash str
     *
     * @param block
     * @return
     */
    public static String getBlockSignStr(Block block) {
        String blockHeaderStr = BlockUtils.getBlockHeaderSignStr(block.getBlockHeader());
        return blockHeaderStr;
    }


    /**
     * 指令签名 hash str
     *
     * @param instruction
     * @return
     */
    public static String getInstructionSignStr(Instruction instruction) {
        String str = new StringBuilder()
                .append(instruction.getOperation())
                .append(instruction.getTable())
                .append(instruction.getInstructionId())
                .append(StringUtils.isBlank(instruction.getJson()) ? "" : instruction.getJson())
                .toString();
        return str;
    }


    /**
     * 区块头hash str
     *
     * @param blockHeader
     * @return
     */
    private static String getBlockHeaderSignStr(BlockHeader blockHeader) {
        String str = new StringBuilder()
                .append(blockHeader.getVersion())
                .append(blockHeader.getHashPreviousBlock())
                .append(blockHeader.getHashMerkleRoot())
                .append(blockHeader.getPublicKey())
                .append(blockHeader.getNumber())
                .append(blockHeader.getTimeStamp())
                .append(blockHeader.getNonce())
                .append(blockHeader.getHashList())
                .append(blockHeader.getExtraData())
                .toString();
        return str;
    }

    /**
     * 获取区块中指令集
     *
     * @param block
     * @return
     */
    public static List<InstructionInfo> block2InstructionInfos(Block block) {
        List<InstructionInfo> list = Lists.newArrayList();
        if (block == null || block.getBlockBody() == null
                || CollUtil.isEmpty(block.getBlockBody().getInstructions())) {
            return list;
        }
        long blockNumber = block.getBlockHeader().getNumber();
        String blockHash = block.getHash();
        AtomicInteger index = new AtomicInteger();
        block.getBlockBody().getInstructions().forEach(e -> {
            InstructionInfo info = new InstructionInfo();
            info.setHash(e.getHash());
            info.setBlockNumber(blockNumber);
            info.setBlockHash(blockHash);
            info.setIndex(index.getAndIncrement());

            list.add(info);
        });
        return list;
    }

}
